/*tickettaker.c*/
#include "cineplex.h"

void TicketTaker_Scheduler(int index)
{
	agentsStarted = agentsStarted + 1;
	Wait(initCond, initLock);
	tixTakers[index].runScheduler = runSchedulers;
	do
	{
		/*ConsoleAcquire();
			Write("TicketTaker ", 12, ConsoleOutput);
			outputLen = Itoa(index, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" SCHED\n", 7, ConsoleOutput);
		ConsoleRelease();*/
		Acquire(tixTakers[index].msgLock);
		if(tixTakers[index].status == TALKINGTOMANAGER)
		{
			/*if(msgList->Find("Okay"))*/
			TicketTaker_GetMessage(index, Okay);
			if(tixTakers[index].tempMsg.sender > -1)
			{
				TicketTaker_ContinueOn(index);
				Release(tixTakers[index].msgLock);
				continue;
			}
			
			/*else if(msgList->Find("GoOnBreak"))*/
			TicketTaker_GetMessage(index, GoOnBreak);
			if(tixTakers[index].tempMsg.sender > -1)
			{
				TicketTaker_GoOnBreak(index);
				Release(tixTakers[index].msgLock);
				continue;
			}
			/*else if(msgList->Find("ComeOffBreak"))*/
			TicketTaker_GetMessage(index, ComeOffBreak);
			if(tixTakers[index].tempMsg.sender > -1)
			{
				TicketTaker_ComeOffBreak(index);
				Release(tixTakers[index].msgLock);
				continue;
			}
		}
		else if(tixTakers[index].status == WAITINGFORCUST)
		{
			/*msg=msgList->Find("HereAreTix");*/
			TicketTaker_GetMessage(index, HereAreTix);
			if(tixTakers[index].tempMsg.sender > -1)
			{
				TicketTaker_AcceptTickets(index, tixTakers[index].tempMsg.sender);
				Release(tixTakers[index].msgLock);
				continue;
			}
		}
		else if(tixTakers[index].status == SENTTOTHEATER)
		{
			/*msg=msgList->Find("ImGoingIn");*/
			TicketTaker_GetMessage(index, ImGoingIn);
			if(tixTakers[index].tempMsg.sender > -1)
			{
				TicketTaker_SendInPerson(index);
				Release(tixTakers[index].msgLock);
				continue;
			}
		}
		else if(tixTakers[index].status == ONBREAK)
		{
			/*msg=msgList->Find("WhatIsStatus");*/
			TicketTaker_GetMessage(index, WhatIsStatus);
			if(tixTakers[index].tempMsg.sender > -1)
			{
				TicketTaker_TellStatus(index);
				Release(tixTakers[index].msgLock);
				continue;
			}
			/*msg=msgList->Find(ISYOURLINEEMPTY);*/
			TicketTaker_GetMessage(index, IsYourLineEmpty);
			if(tixTakers[index].tempMsg.sender > -1)
			{
				/*printf("My line is empty\n");*/
				TicketTaker_TellTechImIdle(index);
				Release(tixTakers[index].msgLock);
				continue;
			}
		}
		else if(tixTakers[index].status == IDLE)
		{
			/*msg=msgList->Find("WhatIsStatus");*/
			TicketTaker_GetMessage(index, WhatIsStatus);
			if(tixTakers[index].tempMsg.sender > -1)
			{
				TicketTaker_TellStatus(index);
				Release(tixTakers[index].msgLock);
				continue;
			}
			else if(TicketTaker_CallNextInLine(index))
			{
				Release(tixTakers[index].msgLock);
				continue;
			}
			/*printf("My line is empty\n");*/
			/*msg=msgList->Find("IsYourLineEmpty");*/
			TicketTaker_GetMessage(index, IsYourLineEmpty);
			if(tixTakers[index].tempMsg.sender > -1)
			{
				/*printf("My line is empty\n");*/
				TicketTaker_TellTechImIdle(index);
				Release(tixTakers[index].msgLock);
				continue;
			}
		}
		Wait(tixTakers[index].sleepCon, tixTakers[index].msgLock);
	} while(tixTakers[index].runScheduler);
	
}

struct Message TicketTaker_GetMessage(int index,int name)
{
	/*this will be the null output*/
	tixTakers[index].tempMsg.name = NullMsg;
	tixTakers[index].tempMsg.sender = NullMsg;
	
	Acquire(loopLock);
	for(i = 0; i < tixTakers[index].numMsgs; i++)
	{
		if(tixTakers[index].msgList[i].name == name)
		{
			tixTakers[index].tempMsg.name = name;
			tixTakers[index].tempMsg.sender = tixTakers[index].msgList[i].sender;
			tixTakers[index].numMsgs = tixTakers[index].numMsgs - 1;
			break;
		}
	}
	for(k = i; k < 2; k++)
	{
		/*movin on up*/
		tixTakers[index].msgList[k].name = tixTakers[index].msgList[k+1].name;
		tixTakers[index].msgList[k].sender = tixTakers[index].msgList[k+1].sender;
	}
	tixTakers[index].msgList[2].name = NullMsg;
	tixTakers[index].msgList[2].sender = NullMsg;
	Release(loopLock);
		
	return tixTakers[index].tempMsg;
}

int  TicketTaker_CallNextInLine(int index)
{
	Acquire(entryLinesLock);
	tixTakers[index].replyTo = entryLines[index].customers[0];
	if(tixTakers[index].replyTo != -1)
	{	
		/*printf("TicketTaker %s has a line length %i\n", myName, myLine->getSize()+1);*/
		ConsoleAcquire();
			Write("TicketTaker ", 12, ConsoleOutput);
			outputLen = Itoa(index, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" has a line length ", 19, ConsoleOutput);
			outputLen = Itoa(Line_getSize(T_TICKETTAKER,index), outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write("\n", 1, ConsoleOutput);
		ConsoleRelease();
		/*cust->SendMessage("ComeBuyTix",1,this);*/
		SendMessage(T_CUSTOMER, tixTakers[index].replyTo, GoToTicketTaker, index);
		Release(entryLinesLock);
		tixTakers[index].status=WAITINGFORCUST;
		return 1;
	}
	Release(entryLinesLock);
	/*printf("TicketClerk %s has no one in line.  I am available for a customer\n", myName);*/
	ConsoleAcquire();
		Write("TicketTaker ", 12, ConsoleOutput);
		outputLen = Itoa(index, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write(" has no one in line.  I am available for a customer\n", 52, ConsoleOutput);
	ConsoleRelease();
	return 0;
}

void TicketTaker_AcceptTickets(int index, int cust)
{
	Acquire(seatingLock);
	if(seatsFilled+groupSizes[groupNums[cust]] <= (NUM_ROWS*NUM_COLS) && !movieStarted && letPeopleIn)
	{
		/*printf ("TicketTaker %s is allowing the group into the theater. The number of tickets taken is %i\n",myName,size);*/
		ConsoleAcquire();
			Write("TicketTaker ", 12, ConsoleOutput);
			outputLen = Itoa(index, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" is allowing leader ", 20, ConsoleOutput);
			outputLen = Itoa(cust, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" into the theater. The number of tickets taken is ", 50, ConsoleOutput);
			outputLen = Itoa(groupSizes[groupNums[cust]], outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write("\n", 1, ConsoleOutput);
		ConsoleRelease();
		seatsFilled += groupSizes[groupNums[cust]];
		/*cust->SendMessage("GoOnIn",2,this,getCineplex()->theater);*/
		SendMessage(T_CUSTOMER, cust, GoOnIn, index);
		tixTakers[index].SizeOfGroupNotInTheater = groupSizes[groupNums[cust]];
		tixTakers[index].status=SENTTOTHEATER;
	}
	else
	{
		/*printf("TicketTaker %s is not allowing the group into the theater. The number of taken tickets is %i and the group size is %i.\n",myName,getCineplex()->theater->seatsFilled,size);*/
		ConsoleAcquire();
			Write("TicketTaker ", 12, ConsoleOutput);
			outputLen = Itoa(index, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" is not allowing leader ", 24, ConsoleOutput);
			outputLen = Itoa(cust, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" into the theater. The number of tickets taken is ", 50, ConsoleOutput);
			outputLen = Itoa(groupSizes[groupNums[cust]], outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write("\n", 1, ConsoleOutput);
		ConsoleRelease();
		/*cust->SendMessage("GoToLobby",1,getCineplex()->lobby);*/
		SendMessage(T_CUSTOMER, cust, GoToLobby, index);
		tixTakers[index].status=IDLE;	
	}
	Release(seatingLock);
}

void TicketTaker_SendInPerson(int index)
{
	tixTakers[index].SizeOfGroupNotInTheater = tixTakers[index].SizeOfGroupNotInTheater - 1;
	if(tixTakers[index].SizeOfGroupNotInTheater==0)
	{
		tixTakers[index].status=IDLE;
	}
}

void TicketTaker_TellTechImIdle(int index)
{
	/*tech->SendMessage("LineIsEmpty",0);*/
	SendMessage(T_MOVIETECH, 0, LineIsEmpty, index);
}

void TicketTaker_TellStatus(int index)
{
	if(tixTakers[index].status==ONBREAK)
	{
		tixTakers[index].onBreak=1;
	}
	else
	{
		tixTakers[index].onBreak=0;
	}
	
	/*manager->SendMessage("NumInLine",2,this,&lineLength);*/
	SendMessage(T_MANAGER, 0, NumInLine, index);
	tixTakers[index].status=TALKINGTOMANAGER;
}

void TicketTaker_ContinueOn(int index)
{
	if(tixTakers[index].onBreak)
	{
		tixTakers[index].status=ONBREAK;
	}
	else
	{
		tixTakers[index].status=IDLE;
	}
}

void TicketTaker_GoOnBreak(int index)
{
	/*printf("TicketClerk %s is going on break\n", myName);*/
	entryLines[index].isOpen=0;
	entryLines[index].length = -1;
	tixTakers[index].status=ONBREAK;
}

void TicketTaker_ComeOffBreak(int index)
{
	/*printf("TicketClerk %s is coming off break\n", myName);*/
	entryLines[index].isOpen=1;
	entryLines[index].length=0;
	tixTakers[index].status=IDLE;
}
